package com.example.form.service.impl;

import com.example.form.common.AppResult;
import com.example.form.common.ResultCode;
import com.example.form.dao.ArticleMapper;
import com.example.form.exception.ApplicationException;
import com.example.form.model.Article;
import com.example.form.model.Board;
import com.example.form.model.User;
import com.example.form.service.IArticleService;
import com.example.form.service.IBoradService;
import com.example.form.service.IUserService;
import com.example.form.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

@Slf4j//打印日志
@Service
public class ArticleServiceImpl implements IArticleService {
    @Resource
    private ArticleMapper articleMapper;//属性注入得到对Article表的操作类
    @Resource
    private IUserService userService;//属性注入得到对User表的操作类
    @Resource
    private IBoradService boradService;//属性注入得到对Borad表的操作类

    @Override
    public void create(Article article) {
        //非空校验
        if (article==null||article.getUserId() == null || article.getBoardId() == null || StringUtil.isEmpty(article.getTitle())
                || StringUtil.isEmpty(article.getContent()) ){
            //打印日志
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());//参数校验失败异常
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        //设置默认值(因为帖子表中有一些值是必须有的,而前端传递来的是没有这些的
        article.setVisitCount(0); // 访问数
        article.setReplyCount(0); // 回复数
        article.setLikeCount(0); // 点赞数
        article.setDeleteState((byte) 0);
        article.setState((byte) 0);
        Date date = new Date();
        article.setCreateTime(date);
        article.setUpdateTime(date);
        //写入数据库
        //1把帖子插入帖子表
        int articleRow=articleMapper.insertSelective(article);//动态插入帖子
        //判断写入的数据是否完成
        if (articleRow <= 0) {
            //打印日志
            log.warn(ResultCode.FAILED_CREATE.toString());//新增失败异常日志
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_CREATE));
        }
        //2把用户的发帖数更新到用户表
        //获取用户数据
        User user=userService.selectById(article.getUserId());//通过文章里面的用户id获取数据库中对应的用户信息
        //没有找到用户信息的情况下
        if(user==null){
            //打印日志
            log.warn(ResultCode.FAILED_CREATE.toString() + ", 发贴失败, user id= " + article.getUserId());
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_CREATE));
        }
        //现在可以更新用户发帖数了(通过id来得到要更新的用户)
        userService.addOneArticleCountById(user.getId());//调用更新方法
        //3把板块的帖子数更新
        //获取板块信息
        Board board = boradService.selectById(article.getBoardId());//通过板块的id获取
        //是否在数据库中有对应的板块
        if (board==null){
            //打印日志
            log.warn(ResultCode.FAILED_CREATE.toString() + ", 发贴失败, board id = " + article.getBoardId());
            //抛出异常
            throw new  ApplicationException(AppResult.failed(ResultCode.FAILED_CREATE));
        }
        //更新板块中的帖子数量
        boradService.addOneArticleCountById(board.getId());//根据板块的id来更新对应的板块帖子数量
        // 打印⽇志
        log.info(ResultCode.SUCCESS.toString() + ", user id = " +
                        article.getUserId()
                        + ", board id = " + article.getBoardId() + ", article id =  "+article.getId() + "发帖成功");
    }
    /**
     * 主⻚中显⽰的帖⼦列表以发布时间降序排列
     *
     * @return 帖⼦列表
     */
    @Override
    public List<Article> selectAll() {
        return articleMapper.selectAll();//没有参数,直接返回查询结果即可
    }

    @Override
    public List<Article> selectByBoardId(Long boardId) {
        //非空校验
        if(boardId==null||boardId<=0){
            //打印日志
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            //抛出异常
            throw  new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        //检验板块是否存在
        Board board=boradService.selectById(boardId);//根据板块id查询对应的板块信息
        if(board==null){
            //板块不存在,打印日志
            log.warn(ResultCode.FAILED_NOT_EXISTS.toString());//资源不存在异常
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_NOT_EXISTS));
        }
        //调用dio查询
        List<Article> articles=articleMapper.selectByBoardId(boardId);//根据板块id查询对应的帖子
        //返回结果
        return articles;
    }

    @Override
    public Article selectDetailById(Long id) {
        //参数校验
        if(id==null||id<=0){
            //打印日志
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        //调用dao根据帖子id查询帖子详情
        Article article=articleMapper.selectDetailById(id);
        //判断结果是否为空
        if(article==null){
            //打印日志
            log.warn(ResultCode.FAILED_NOT_EXISTS.toString());//资源不存在
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_NOT_EXISTS));
            //抛出异常
        }
        //更新帖子的访问数量,调用updateByPrimaryKeySelective方法,根据帖子id来动态修改对应的数据
        Article updateArticle=new Article();//得到全新的article对象,为了等下更新
        updateArticle.setId(article.getId());//设置id
        updateArticle.setVisitCount(article.getVisitCount()+1);//在我们通过id查询到的帖子的原因的访问的数量上加一
        //保存到数据库
        int row=articleMapper.updateByPrimaryKeySelective(updateArticle);//执行修改操作,把数据库中的数据更新
        //判断执行是否正常
        if(row!=1){//错误的执行
            //打印日志
            log.warn(ResultCode.FAILED.toString());//操作失败异常
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED));
        }
        //更新返回对象的访问次数,因为article里面是我们第一次查询的,还没有更新,重新查询的话访问数据库太慢,所以直接设置属性访问数量加一即可
        article.setVisitCount(article.getVisitCount()+1);//在原来查询到的次数上加一
        return article;//把设置号的访问数量的帖子表返回获取
    }

    @Override
    public void modify(Long id, String title, String content) {
        //非空校验
        if(id==null||StringUtil.isEmpty(title)||StringUtil.isEmpty(content)){
            //打印日志
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        //构建要更新的帖子的对象(因为是动态修改,所以我们只要把要更新的属性设置前端的参数即可
        Article updateArticle=new Article();
        updateArticle.setId(id);//帖子id
        updateArticle.setTitle(title);//标题
        updateArticle.setContent(content);//正文
        updateArticle.setUpdateTime(new Date());//修改的时间
        //调用dao执行修改操作
        int row=articleMapper.updateByPrimaryKeySelective(updateArticle);//根据id找到帖子,然后变动内容
        //判断执行的结果
        if(row!=1){//执行失败
            //打印日志
            log.warn(ResultCode.FAILED.toString());//操作失败异常
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_CREATE));
        }
    }

    @Override
    public Article selectById(Long id) {
        //非空校验
        if(id==null||id<=0){
            //打印日志
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        //调用dao
        Article article=articleMapper.selectByPrimaryKey(id);
        //返回结果
        return article;
    }

    @Override
    public void thumbsUpById(Long id) {
        //非空校验
        if(id==null||id<=0){
            //打印日志
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        //获取帖子详情
        Article article=articleMapper.selectByPrimaryKey(id);//通过帖子的id获取对应的详细信息
        //帖子不存在的时候
        if(article==null){
            //板块不存在,打印日志
            log.warn(ResultCode.FAILED_NOT_EXISTS.toString());//资源不存在异常
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_NOT_EXISTS));
        }
        //帖子存在,但是状态异常的情况
        if(article.getDeleteState()==1||article.getState()==1){//被禁言或结贴状态
            //打印日志
            log.warn(ResultCode.FAILED_USER_BANNED.toString());//已经被禁言的异常信息
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_BANNED));
        }
        //构造要更新的帖子对象
        Article updateArticle=new Article();
        updateArticle.setId(article.getId());//设置帖子id
        updateArticle.setLikeCount(article.getLikeCount()+1);//点赞数量加一
        updateArticle.setUpdateTime(new Date());//设置修改时间
        //调用dao
        int row=articleMapper.updateByPrimaryKeySelective(updateArticle);//执行动态修改操作
        //判断执行的结果
        if(row!=1){
            //打印日志
            log.warn(ResultCode.FAILED.toString());//打印操作失败异常
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED));
        }
    }

    @Override
    public void deleteById(Long id) {
        //非空校验
        if(id==null||id<=0){
            //打印日志
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        //获取帖子详情
        Article article=articleMapper.selectByPrimaryKey(id);//通过帖子的id获取对应的详细信息
        //帖子不存在的时候
        if(article==null){
            //板块不存在,打印日志
            log.warn(ResultCode.FAILED_NOT_EXISTS.toString());//资源不存在异常
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_NOT_EXISTS));
        }
        //构造要更新的帖子对象
        Article updateArticle=new Article();
        updateArticle.setId(article.getId());//设置帖子id
        updateArticle.setDeleteState((byte) 1);//设置帖子的状态为1,表示删除
        //调用dio,更新帖子信息
        int row= articleMapper.updateByPrimaryKeySelective(updateArticle);//根据id动态修改当前帖子的信息
        //判断执行的结果
        if(row!=1){
            //打印日志
            log.warn(ResultCode.FAILED.toString());//打印操作失败异常
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED));
        }
        //更新对应板块中的帖子数量
        boradService.subOneArticleCountById(article.getBoardId());//通过帖子信息获取板块的id设置进去
        //更新对应用户的发帖数量
        userService.subOneArticleCountById(article.getUserId());//通过帖子信息获取用户的id设置进去
        //打印日志
        log.info("删除帖子成功 帖子id"+article.getId()+"  用户id:"+article.getUserId());
    }

    @Override
    public void addOneReplyCountById(Long id) {
        //非空校验
        if(id==null||id<=0){
            //打印日志
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        //获取帖子详情
        Article article=articleMapper.selectByPrimaryKey(id);//通过帖子的id获取对应的详细信息
        //帖子不存在的时候
        if(article==null){
            //板块不存在,打印日志
            log.warn(ResultCode.FAILED_NOT_EXISTS.toString());//资源不存在异常
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_NOT_EXISTS));
        }
        //帖子存在,但是状态异常的情况
        if(article.getDeleteState()==1||article.getState()==1){//被禁言或结贴状态
            //打印日志
            log.warn(ResultCode.FAILED_USER_BANNED.toString());//已经被禁言的异常信息
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_BANNED));
        }
        //构造要更新的帖子对象
        Article updateArticle=new Article();
        updateArticle.setId(article.getId());//设置帖子id
        //回复数等于原回复数加一
        updateArticle.setReplyCount(article.getReplyCount()+1);
        //修改时间
        updateArticle.setUpdateTime(new Date());
        int row= articleMapper.updateByPrimaryKeySelective(updateArticle);//根据id动态修改当前帖子的信息
        //判断执行的结果
        if(row!=1){
            //打印日志
            log.warn(ResultCode.FAILED.toString());//打印操作失败异常
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED));
        }
    }

    @Override
    public List<Article> selectByUserId(Long userId) {
        //非空校验
        //非空校验
        if(userId==null||userId<=0){
            //打印日志
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        //校验当前用户是否存在
        User user=userService.selectById(userId);//根据传递来的用户id来查询对应的用户信息
        if(user==null){
            //打印日志
            log.warn(ResultCode.FAILED_NOT_EXISTS.toString());//资源不存在
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_NOT_EXISTS));
        }
        //调用dao
        List<Article> articles=articleMapper.selectByUserId(userId);//调用service中的方法,通过用户id来查询用户所发的帖子的信息
        //返回结果
        return articles;
    }

}
